﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO; 

namespace DupeKill.Core.Discovery
{
    internal class DirectoryFileIterator : IFileIterator 
    {
        private string root;
        private IEnumerator<FileInfo> enumerator; 

        public DirectoryFileIterator(string root)
        {
            if (string.IsNullOrEmpty(root))
                throw new ArgumentException();

            this.root = root; 
        }

        #region IFileIterator Member

        public string Directory
        {
            get 
            {
                return Path.GetDirectoryName(FullPath); 
            }
        }

        public string FileName
        {
            get 
            {
                return Path.GetFileName(FullPath);
            }
        }

        public string FullPath
        {
            get 
            {
                if (enumerator == null)
                    return null;

                return enumerator.Current.FullName; 
            }
        }

        public long Length
        {
            get 
            {
                if (enumerator == null)
                    return -1;

                return enumerator.Current.Length; 
            }
        }

        public void Reset()
        {
            TryDisposeEnumerator();

            enumerator = EnumerateCore().GetEnumerator(); 
        }

        public bool Next()
        {
            if (enumerator == null)
                throw new InvalidOperationException();

            if (enumerator.MoveNext())
                return true;

            TryDisposeEnumerator();
            return false; 
        }

        #endregion

        #region IDisposable Member

        public void Dispose()
        {
            TryDisposeEnumerator();
        }

        private void TryDisposeEnumerator()
        {
            if (enumerator != null)
            {
                enumerator.Dispose();
                enumerator = null;
            }
        }

        #endregion

        private IEnumerable<FileInfo> EnumerateCore()
        {
            return EnumerateCore(root); 
        }

        private IEnumerable<FileInfo> EnumerateCore(string directory)
        {
            foreach (string pathOfFile in System.IO.Directory.GetFiles(directory))
            {
                FileInfo result = null; 
                try
                {
                    result = new FileInfo(pathOfFile);
                }
                catch
                {
                }

                if (result != null)
                    yield return result; 
            }

            foreach (string pathOfDirectory in System.IO.Directory.GetDirectories(directory))
            {
                foreach (FileInfo file in EnumerateCore(pathOfDirectory))
                {
                    yield return file;
                }
            }         
        }
    }
}
